package com.github.dtkavin.bgq.graph_meta

import java.sql.ResultSet

import com.alibaba.fastjson.{JSON, JSONObject}
import com.github.dtkavin.bgq.utils.MysqlUnits
import org.neo4j.driver.v1.Session

import scala.collection.mutable.ArrayBuffer

/**
  * Function: Neo4j业务相关操作
  * neo4j类型:
  *
  * WhsLog 原始日志
  * WhsTable 仓库表
  * WhsShip 仓库依赖关系
  * WhsProduct 产品信息
  * WhsLogPtl 仓库用到的日志协议
  * WhsLogEt 仓库基础日志类型
  *
  * #Author: john 
  * #Create: 2018 04 03 下午4:30 
  */
object Neo4jHelper extends Neo4JUtils {

  /**
    * 顶点插入
    */
  //　TABLE{name:typ} 一层的ｊｓｏｎ
  def nodeInsert(tableType: String, tableName: String, fieldsJ: JSONObject): Unit = {

    //从mysql查询
    //todo 做成接口　
    val sql = s"select ${fieldsJ.keySet().toArray.mkString(",")} from ${tableName}"
    log.isDebugEnabled match {
      case true => log.debug(s"nodeInster sql : ${sql}")
    }

    val fun: Function[ResultSet, List[(String, String, String)]] = (rs) => {
      val jsonObj = new JSONObject()
      val arr = new ArrayBuffer[(String, String, String)]()
      while (rs.next()) {
        jsonObj.clear()
        fieldsJ.keySet().toArray.map {
          name => {
            val typ = fieldsJ.get(name).asInstanceOf[String]
            typ.toLowerCase match {
              case "int" => jsonObj.put(name.toString, rs.getInt(name.toString))
              case "string" => jsonObj.put(name.toString, rs.getString(name.toString))
              case "long" => jsonObj.put(name.toString, rs.getLong(name.toString))
              case "boolean" => jsonObj.put(name.toString, rs.getBoolean(name.toString))
              case _ => log.debug("case type not exist")
            }
          }
        }
        arr.append((tableType, tableName, jsonObj.toJSONString))
      }
      arr.toList
    }

    val tableList = MysqlUnits.query(sql, fun)

    //插入neo4j
    val funNeo4j: Session => Unit = {
      session => {
        tableList.foreach {
          case (tableType, tableName, json) if tableType.equals("OriginLog") =>
          case (tableType, tableName, json) if tableType.equals("WhsTable") => {
            val struct = json.replaceAll(",\"", ",").replaceAll("\":", ":").replace("{\"", "{")
            val cypyer = s"create (a:${tableType}${struct})"
            session.run(cypyer)
            Thread.sleep(100)
          }
        }
      }
    }
    do2Unit(funNeo4j)
  }

  /**
    * 边－插入
    */
  def relationShipInsert(): Unit = {
    //从mysql查询
    val sql = "select id,sources_table,target_table,`sql`,description,create_time,update_time from atlas.conf_table_build"
    val fun: Function[ResultSet, List[WhsRelationShip]] = (rs) => {
      val array: ArrayBuffer[WhsRelationShip] = new ArrayBuffer()
      while (rs.next()) {
        val id = rs.getInt("id")
        val sources_table = rs.getString("sources_table")
        val target_table = rs.getString("target_table")
        val build_sql = rs.getString("sql")
        val description = rs.getString("description")
        val create_time = rs.getString("create_time")
        val update_time = rs.getString("update_time")
        val ship = WhsRelationShip(id, sources_table, target_table, build_sql, description, create_time, update_time)
        array.append(ship)
      }
      array.toList
    }
    val tableList = MysqlUnits.query(sql, fun)

    //插入neo4j
    val funNeo4j: Session => Unit = {
      session => {
        tableList.foreach {
          ship => session.run(s"match (a:Table{name:'${ship.sources_table}'}),(b:Table{name:'${ship.target_table}'}) create (a) -[r:RelationShip{build_sql:'${ship.sql}',description:'${ship.description}',create_time:'${ship.createTime}',update_time:'${ship.updateTime}'}]->(b) return type(r)")
        }
      }
    }
    do2Unit(funNeo4j)
  }

  def findNodeByString(cypyer: String, field: String): List[String] = {
    do2List {
      session =>
        val results = session.run(cypyer)
        val buffer = new ArrayBuffer[String]()
        while (results.hasNext) {
          val record = results.next()

          buffer.append(record.get(field).toString)
        }
        buffer.toList
    }
  }

  //  CREATE CONSTRAINT ON (cc:WhsTable) ASSERT (cc.db_name,cc.name) IS NODE KEY
  def whsTableInsert(): Unit = {
    val tableName = "apus_atlas.whse_table"
    val tableType = "WhsTable"
    val schema ="""{"id":"int","name":"string","category":"string","time_zone":"string","path":"string","level":"int","description":"string","create_time":"string","update_time":"string","live_cycle":"int","db_name":"string","monitor":"string","partitions":"string"}"""
    nodeInsert(tableType, tableName, JSON.parseObject(schema))
  }

  def whsShipInsert(): Unit = {

  }

  def main(args: Array[String]): Unit = {
    whsShipInsert()
  }

}
